package com.inplaceedit.client.ui.phone;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.client.adapters.EditorSource;
import com.google.gwt.editor.client.adapters.ListEditor;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Widget;
import com.inplaceedit.client.ui.ListItemPanel;
import com.inplaceedit.shared.dto.DtoFactory;
import com.inplaceedit.shared.dto.PhoneDto;

public class PhoneListEditorView extends Composite implements
		IsEditor<ListEditor<PhoneDto, PhoneEditor>> {

	interface Binder extends UiBinder<Widget, PhoneListEditorView> {
	}

	private class PhoneEditorSource extends EditorSource<PhoneEditor> {
		private final Map<PhoneEditor, Widget> widgetIndex = new HashMap<PhoneEditor, Widget>();
		private final Map<PhoneEditor, HandlerRegistration> deleteHandlerIndex = new HashMap<PhoneEditor, HandlerRegistration>();

		@Override
		public PhoneEditor create(final int index) {
			final PhoneEditorView editor = new PhoneEditorView();

			// Wrap the editor in a ListItemPanel (padding plus a 'delete'
			// command)
			final ListItemPanel widget = new ListItemPanel();
			widget.setContentWidget(editor);

			// Add the panel to the widget index
			widgetIndex.put(editor, widget);

			// Add the delete click handler
			deleteHandlerIndex.put(editor, widget.getDeleteCommand()
					.addClickHandler(new ClickHandler() {
						@Override
						public void onClick(final ClickEvent event) {
							final int indexToDelete = listPanel
									.getWidgetIndex(widget);
							if (indexToDelete >= 0) {
								listEditor.getList().remove(indexToDelete);
							}
						}
					}));

			// Add the panel to the list container
			listPanel.insert(widget, index);

			// Give the focus to the new editor
			if (editor.asFocusable() != null) {
				editor.asFocusable().setFocus(true);
			}

			return editor;
		}

		@Override
		public void dispose(final PhoneEditor editor) {
			// Remove the delete click handler
			final HandlerRegistration deleteRegistration = deleteHandlerIndex
					.get(editor);
			if (deleteRegistration != null) {
				deleteRegistration.removeHandler();
			}
			deleteHandlerIndex.remove(editor);

			// Remove the widget from the list container
			final Widget w = widgetIndex.get(editor);
			if (w != null) {
				listPanel.remove(w);
			}
			widgetIndex.remove(editor);
		}

		@Override
		public void setIndex(final PhoneEditor editor, final int index) {
			final Widget w = widgetIndex.get(editor);
			if (w != null) {
				listPanel.insert(w, index);
			}
		}
	}

	private static Binder uiBinder = GWT.create(Binder.class);
	private static final DtoFactory factory = GWT.create(DtoFactory.class);

	@UiField
	FlowPanel listPanel;
	@UiField
	Anchor addCommand;

	private final ListEditor<PhoneDto, PhoneEditor> listEditor = ListEditor
			.of(new PhoneEditorSource());

	public PhoneListEditorView() {
		initWidget(uiBinder.createAndBindUi(this));
	}

	@Override
	public ListEditor<PhoneDto, PhoneEditor> asEditor() {
		return listEditor;
	}

	@UiHandler("addCommand")
	void onAddCommandClick(final ClickEvent event) {
		if (listEditor.getList() != null) {
			final PhoneDto item = factory.createPhone().as();
			item.setType(PhoneDto.Type.BUSINESS);
			listEditor.getList().add(item);
		}
	}
}
